<template>
  <div class="virtual-list-wrapper">
    <div class="virtual-list-header">
      <div 
        v-for="(col, index) in columns" 
        :key="index"
        class="title-cell"
        :style="{ flex: col.flex || 1 }"
      >
        {{ col.title }}
      </div>
    </div>
    <div class="virtual-list-container" ref="containerRef">
      <div
        class="virtual-list-phantom"
        :style="{ height: totalHeight + 'px' }"
      ></div>
      <div
        class="virtual-list-content"
        :style="{ transform: `translate3d(0, ${offset}px, 0)` }"
      >
        <div
          v-for="item in visibleData"
          :key="item.id"
          class="virtual-list-item"
          :style="{ height: itemHeight + 'px' }"
        >
          <div 
            v-for="(col, index) in columns" 
            :key="index"
            class="item-cell"
            :style="{ flex: col.flex || 1 }"
          >
            {{ item[col.key] }}
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { column } from "element-plus/es/components/table-v2/src/common.mjs";
import { ref, computed, onMounted, onUnmounted, watch } from "vue";

const props = defineProps({
  // 列表数据
  data: {
    type: Array,
    required: true,
  },
  // 每项高度
  itemHeight: {
    type: Number,
    required: true,
  },
  // 可视区域高度
  containerHeight: {
    type: Number,
    default: 200,
  },
  // 列配置
  columns: {
    type: Array,
    required: true,
    validator: (value) => {
      return value.every(col => 
        typeof col.title === 'string' && 
        typeof col.key === 'string'
      );
    }
  },
});

// 容器引用
const containerRef = ref(null);
// 滚动偏移量
const offset = ref(0);
// 开始索引
const startIndex = ref(0);
// 结束索引
const endIndex = ref(0);

// 计算总高度
const totalHeight = computed(() => props.data.length * props.itemHeight);

// 计算可视区域能显示的项目数量
const visibleCount = computed(() =>
  Math.ceil(props.containerHeight / props.itemHeight)
);

// 计算当前可见的数据
const visibleData = computed(() => {
  return props.data.slice(startIndex.value, endIndex.value);
});

// 计算开始和结束索引
const calculateRange = () => {
  const start = Math.floor(offset.value / props.itemHeight);
  const end = start + visibleCount.value + 1; // 多渲染一个，防止滚动时出现空白

  startIndex.value = Math.max(0, start);
  endIndex.value = Math.min(props.data.length, end);
};

// 处理滚动事件
const handleScroll = () => {
  if (containerRef.value) {
    offset.value = containerRef.value.scrollTop;
    calculateRange();
  }
};

// 监听数据变化
watch(
  () => props.data,
  () => {
    calculateRange();
  },
  { deep: true }
);

// 组件挂载时添加滚动监听
onMounted(() => {
  if (containerRef.value) {
    containerRef.value.addEventListener("scroll", handleScroll);
    calculateRange();
  }
});

// 组件卸载时移除滚动监听
onUnmounted(() => {
  if (containerRef.value) {
    containerRef.value.removeEventListener("scroll", handleScroll);
  }
});
</script>

<style scoped>
.virtual-list-wrapper {
  display: flex;
  flex-direction: column;
  height: v-bind('containerHeight + "px"');
  background: transparent;
}

.virtual-list-header {
  display: flex;
  background: transparent;
  border-bottom: 1px solid #ebeef5;
  position: sticky;
  top: 0;
  z-index: 2;
}

.virtual-list-container {
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  position: relative;
  background: transparent;
}

.virtual-list-phantom {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  z-index: -1;
}

.virtual-list-content {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  will-change: transform;
}

.title-cell {
  padding: 12px 8px;
  font-weight: bold;
  color: #8e8f8f;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

.virtual-list-item {
  display: flex;
  border-bottom: 1px solid #ebeef5;
  background: transparent;
}

.virtual-list-item:hover {
  background-color: rgba(245, 247, 250, 0.5);
}

.item-cell {
  padding: 12px 8px;
  color: #ffffff;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}
/* Webkit浏览器 */
::-webkit-scrollbar {
  width: 1px;
  height: 1px;
}

::-webkit-scrollbar-track {
  background: #1e1d1d;
  border-radius: 2px;
}

::-webkit-scrollbar-thumb {
  background-color: #2f303160;
  border-radius: 2px;
}

::-webkit-scrollbar-thumb:hover {
  background-color: #2f303160;
}
</style>
